﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CSharpExperiments.Metaprogramming;

namespace CSharpExperiments
{
	public static class NMatrix
	{
		public static NMatrix<T, Nat2, Nat3> Create2x3<T>(T v1, T v2, T v3, T v4, T v5, T v6)
		{
			return new NMatrixImpl<T, Nat2, Nat3>(new T[][]{new T[]{v1, v2, v3}, new T[]{v4, v5, v6}});
		}

		public static T Get<T, M, N, I, J>(this NMatrix<T, M, N> matrix, I i, J j)
			where I : Natural, new()
			where J : Natural, new()
			where M : I, Natural, new()
			where N : J, Natural, new()
		{
			return matrix.Do<T>("GetUnsafe", Naturals.Value<I>(), Naturals.Value<J>());
		}

		private class NMatrixImpl<T, M, N> : NMatrix<T, M, N>
			where M : Natural, new()
			where N : Natural, new()
		{
			private T[][] vals;

			internal NMatrixImpl(T[][] vals) { this.vals = vals; }
			
			public T GetUnsafe(int i, int j) { return vals[i][j]; }

			public int Length { get { return Naturals.Value<M>(); } }
			
			public int Height { get { return Naturals.Value<N>(); } }
		}
	}

	public interface NMatrix<T, out M, out N>
		where M : Natural, new()
		where N : Natural, new()
	{
		int Length { get; }
		int Height { get; }
	}
}
